import fs from "fs";
import pako from "pako";
import archiver from "archiver";
import { pinyin } from "pinyin-pro";
import mime from "mime-types";
import path, { sep, parse } from "path";
import { IBuildTaskOption, IBuildResult } from "../@types";

const FILE_MAPPING = {};
const L10N_JSON = { "l10n_country_codes": [] };
let OPTIONS: IBuildTaskOption;
let OUTPUT_PATH = "";
let PARAMS = {} as {
  libs: object,
  cullingWasm: boolean,
  cullingAsm: boolean,
  isDeflate: boolean,
  logger: boolean,
  inlineHtml: boolean,
  loadingPage: string,
  scriptPrefix: string,
  playableId: string,
  playableName: string,
  adPlatform: string,
  isIos: string,
  isAndroid: string,
  androidUrl: string,
  iosUrl: string,
  editorVersion: string,
  countryCodes: string,
  comPressInstall: boolean,
  WZ_autoPackage: boolean
};
let INDEX_TEMPLATE = "";
const DAPI_HEAD_STR = "";
let SETUP_STR = "";
const libsNameArr = ["tweenMax"];

export const compile = function (options, result: IBuildResult) {
  const { inlineHtml } = options["packages"]["tk-inline-html"];
  if (inlineHtml) {
    OPTIONS = options;
    OUTPUT_PATH = result.dest;
    PARAMS = Object.assign({}, options["packages"]["tk-inline-html"], { editorVersion: fetchEditorVersion() });

    const scripts = [], mapping = {};
    init();
    judgeIndexTemplate();
    importLibsScript();
    compileEngine(scripts);
    compileProject(scripts, mapping);
    resolveMapping(mapping);

    if (PARAMS.adPlatform == "bigo") {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#bigo_head}", `<script src="https://static-web.likeevideo.com/as/common-static/big-data/dsp-public/bgy-mraid-sdk.js"></script>`)
    } else {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#bigo_head}", "")
    }
    if (PARAMS.adPlatform == "uac") {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#uac_head}", `<script type="text/javascript" src="https://tpc.googlesyndication.com/pagead/gadgets/html5/api/exitapi.js"> </script>`)
        .replace("{#uac_meta}", `<meta data-name="ad.orientation" content="portrait,landscape">`)
    } else {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#uac_head}", "")
        .replace("{#uac_meta}", "")
    }

    if (PARAMS.adPlatform == "tiktok") {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#TK_head}", `<script src= "https://sf16-muse-va.ibytedtos.com/obj/union-fe-nc-i18n/playable/sdk/playable-sdk.js"></script>`)
    } else {
      INDEX_TEMPLATE = INDEX_TEMPLATE
        .replace("{#TK_head}", "")
    }

    INDEX_TEMPLATE = INDEX_TEMPLATE
      .replace("{#dapi_head}", DAPI_HEAD_STR)
      .replace("{#css}", readFile(`${OUTPUT_PATH}${sep}style.css`))
      .replace("<script>{#polyfills}</script>", "<script>{#polyfills}</script>\n" + resolveBundle(`..${sep}src${sep}chunks${sep}bundle.js`, mapping["chunks/bundle.js"]))
      .replace("{#polyfills}", complieFile(
        [
          `${OUTPUT_PATH}${sep}src${sep}polyfills.bundle.js`,
          `${OUTPUT_PATH}${sep}src${sep}system.bundle.js`,
        ]
      ))
      .replace("{#setup}", SETUP_STR);

    copyL10nMapping();
    const l10n_country_codes = !PARAMS.countryCodes ? Array.from(new Set(L10N_JSON["l10n_country_codes"])) : PARAMS.countryCodes.split(",");
    if (l10n_country_codes.length == 0) {
      complieAssetsIndex(scripts, null);
      complieAssetsResource(mapping, null);
      INDEX_TEMPLATE = INDEX_TEMPLATE.replace("{#resource}", `window.resMap = ${JSON.stringify(mapping)}`).replace("{#main}", scripts.join(""));
      fs.writeFileSync(`${OUTPUT_PATH}${sep}${PARAMS.playableName}.html`, INDEX_TEMPLATE);
    } else {
      l10n_country_codes.forEach(country_code => {
        const country_scripts = scripts.slice(), country_mapping = JSON.parse(JSON.stringify(mapping));
        complieAssetsIndex(country_scripts, country_code);
        complieAssetsResource(country_mapping, country_code);
        const l10n_index_template = INDEX_TEMPLATE.slice().replace("{#resource}", `window.resMap = ${JSON.stringify(country_mapping)}`).replace("{#main}", country_scripts.join(""));

        if (PARAMS.WZ_autoPackage) {  //网赚自动打包
          WZ_createDir(l10n_country_codes, l10n_index_template, country_code)
        } else {
          fs.writeFileSync(`${OUTPUT_PATH}${sep}${PARAMS.playableName}_${country_code}.html`, l10n_index_template);
        }
      });
    }
    console.log("<--------- success --------->");
  }
};

//网赚创建目录
const WZ_total_data = { year: "", month: "", day: "", name: "" }
const baseDirName = "${{productName}}_${{phoneType}}_${{platform}}_${{dirName}}_${{countryNum}}_PA_${{date}}_${{owner}}"
function WZ_createDir(l10n_country_codes, l10n_index_template, country_code) {
  //判断下是否存在个人配置 存在的话把文件夹也一起创建了
  let date = new Date()
  let year = date.getFullYear().toString().substring(2, 4)
  let month = (date.getMonth() + 1).toString(); // 获取月份（注意要加1）
  let day = date.getDate().toString(); // 获取日期
  if (month.length === 1) {
    month = "0" + month
  }
  if (day.length === 1) {
    day = "0" + day
  }
  WZ_total_data.year = year
  WZ_total_data.month = month
  WZ_total_data.day = day

  if (PARAMS.adPlatform == "mintegral") {//mtg的文件名应该是拼音
    WZ_total_data.name = pinyin(PARAMS.playableName, {
      toneType: 'none', pattern: 'pinyin', type: 'string', separator: '', nonZh: 'consecutive', v: true
    });
  } else {
    WZ_total_data.name = PARAMS.playableName
  }

  let DirName = null
  if (fs.existsSync(path.join(Editor.Project.path, "个人配置/config.json"))) {

    let baseCfg = fs.readFileSync(path.join(Editor.Project.path, "个人配置/config.json"), "utf8")
    baseCfg = JSON.parse(baseCfg)

    let exclude = baseCfg["exclude"]
    if (exclude && exclude.includes(country_code)) return

    //得到一共多少个国家
    let dirCountryString = country_code
    let totalNum = 0
    l10n_country_codes.forEach(item => {
      if (item.length > 2 || (exclude && exclude.includes(item))) return
      totalNum++
    })
    if (totalNum === 1) {
      dirCountryString = country_code.length > 2 ? country_code.substring(0, 2) : country_code
    } else {
      dirCountryString = totalNum + "国"
    }

    let roleName = baseCfg["roleName"]
    let ProductArr = baseCfg["ProductArr"]
    let productShort = ""
    let phoneType = ""
    if (PARAMS.androidUrl && PARAMS.iosUrl) {
      phoneType = "AND&&IOS"
    } else if (PARAMS.androidUrl) {
      phoneType = "AND"
    } else if (PARAMS.iosUrl) {
      phoneType = "IOS"
    } else {
      phoneType = "未知手机类型"
    }
    for (const key in ProductArr) {
      let IOSURL = ProductArr[key]["IOS"]
      let ANDURL = ProductArr[key]["AND"]
      if ((IOSURL && ProductArr === PARAMS.iosUrl) || (ANDURL && PARAMS.androidUrl === ANDURL)) {
        productShort = key
        break
      }
    }
    if (!productShort) productShort = "${{productName}}"
    let platformShort = ""
    baseCfg["platFormShort"] && baseCfg["platFormShort"][PARAMS.adPlatform] ?
      platformShort = baseCfg["platFormShort"][PARAMS.adPlatform] : platformShort = "${{platform}}"
    DirName = JSON.parse(JSON.stringify(baseDirName))
    DirName = DirName
      .replace("${{productName}}", productShort)
      .replace("${{phoneType}}", phoneType)
      .replace("${{platform}}", platformShort)
      .replace("${{dirName}}", PARAMS.playableName)
      .replace("${{countryNum}}", dirCountryString)
      .replace("${{date}}", year + month + day)
      .replace("${{owner}}", roleName)


    WZ_Pack_Func(l10n_index_template, country_code, DirName)
    return
  }
  WZ_Pack_Func(l10n_index_template, country_code, null)
}


const WZFileNAME = "PA_${{name}}_${{country}}_${{Language}}_${{date}}"//网赚文件名
//网赚项目统一改名打包
function WZ_Pack_Func(script, country_code, fileDir) {
  //国家对应的语言
  let countryTolanguage = fs.readFileSync(path.join(`${__dirname + sep}..${sep}`, "static/WZ_Config/countryTolanguage.json"), "utf8")
  countryTolanguage = JSON.parse(countryTolanguage)

  let language = countryTolanguage["countryToLanguage"][country_code]
  let name = JSON.parse(JSON.stringify(WZFileNAME))

  let country_name = country_code
  country_code.length > 2 ? country_name = country_code.substring(0, 2) : country_name = country_code

  name = name
    .replace("${{name}}", WZ_total_data.name)
    .replace("${{country}}", country_name)
    .replace("${{Language}}", language)
    .replace("${{date}}", WZ_total_data.month + WZ_total_data.day)

  if (fileDir) {
    if (!fs.existsSync(path.join(OUTPUT_PATH, fileDir))) {
      fs.mkdirSync(path.join(OUTPUT_PATH, fileDir))
    }
    name = fileDir + sep + name
  }

  if (PARAMS.adPlatform == "bigo" || PARAMS.adPlatform == "tiktok") {//打成带配置文件的ZIP
    fs.mkdirSync(path.join(OUTPUT_PATH, name))
    fs.writeFileSync(path.join(OUTPUT_PATH, `${name + sep}index.html`), script);
    if (PARAMS.adPlatform == "bigo") {
      fs.writeFileSync(path.join(OUTPUT_PATH, `${name + sep}config.json`), readFile(path.join(`${__dirname + sep}..${sep}`, "static/WZ_Config/config_Bigo.json")));
      createArchiverZIP(name, false, false)
    } else {
      fs.writeFileSync(path.join(OUTPUT_PATH, `${name + sep}config.json`), readFile(path.join(`${__dirname + sep}..${sep}`, "static/WZ_Config/config_TK.json")));
      createArchiverZIP(name, false, true)
    }
  } else if (PARAMS.adPlatform == "mintegral" || PARAMS.adPlatform == "uac") { //ZIP
    fs.writeFileSync(path.join(OUTPUT_PATH, `${name}.html`), script);
    createArchiverZIP(name, true, false)
  } else {
    fs.writeFileSync(path.join(OUTPUT_PATH, `${name}.html`), script);
  }
}

//打包zip
function createArchiverZIP(filename1, isFile, keepDir, callback = null) {
  const output = fs.createWriteStream(path.join(OUTPUT_PATH, `${filename1}.zip`));
  const archive = archiver('zip', {
    zlib: { level: 9 }
  });

  // 监听错误事件
  archive.on('error', function (err) {
    throw err;
  });

  archive.pipe(output);

  let path1 = path.join(OUTPUT_PATH, filename1)
  let name = path.parse(path1).name

  if (isFile) {
    archive.append(fs.createReadStream(path.join(OUTPUT_PATH, `${filename1}.html`)), { name: name + ".html" })
  } else {//是目录
    if (keepDir) {
      archive.directory(path1, name); // 第二个参数为false表示不保留文件夹结构，如果想保留则设置为文件夹名
    } else {
      archive.directory(path1, false);
    }
  }

  archive.finalize();
  // 处理完成
  output.on('close', () => {
    isFile ? fs.unlinkSync(path.join(OUTPUT_PATH, filename1 + ".html")) : delDir(path1)
    if (callback) callback()
  });
}

function delDir(path) {
  let files = [];
  if (fs.existsSync(path)) {
    files = fs.readdirSync(path);
    files.forEach((file, index) => {
      let curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) {
        delDir(curPath); //递归删除文件夹
      } else {
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}

function fetchEditorVersion() {
  const versionArr = Editor.App.version.split(".");
  const editorVersion = `${versionArr[0]}.${parseInt(versionArr[1]) >= 6 ? "6" : "5"}`;
  return editorVersion;
}

function copyL10nMapping() {
  const { buildPath, outputName, scenes } = OPTIONS;
  const outputPath = `${buildPath}${sep}${outputName}`.replace("project://", "");
  scenes.forEach(scene => {
    const { url } = scene;
    const parts = url.split("/").filter(v => v != '');
    const scene_root_dir = parts[parts.indexOf("scenes") + 1];
    const exist = fs.existsSync(`${__dirname}${sep}..${sep}..${sep}..${sep}assets${sep}scenes${sep}${scene_root_dir}${sep}${scene_root_dir}_l10n.json`);
    if (exist) {
      const json_str = readFile(`${__dirname}${sep}..${sep}..${sep}..${sep}assets${sep}scenes${sep}${scene_root_dir}${sep}${scene_root_dir}_l10n.json`);
      const json = JSON.parse(json_str);
      Object.assign(L10N_JSON, json, { l10n_country_codes: L10N_JSON["l10n_country_codes"].concat(json["l10n_country_codes"]) })
    }
  });
  const common_l10n_files = [`images${sep}images_l10n.json`];
  common_l10n_files.forEach(v => {
    const exist = fs.existsSync(`${__dirname}${sep}..${sep}..${sep}..${sep}assets${sep}${v}`);
    if (exist) {
      const json_str = readFile(`${__dirname}${sep}..${sep}..${sep}..${sep}assets${sep}${v}`);
      const json = JSON.parse(json_str);
      Object.assign(L10N_JSON, json, { l10n_country_codes: L10N_JSON["l10n_country_codes"] });
    }
  });
}

function init() {
  FILE_MAPPING["./application.js"] = "application";
  FILE_MAPPING["application.js"] = "application";
  FILE_MAPPING["./index.js"] = "index";
  FILE_MAPPING["index.js"] = "index";

  const dirs = fs.readdirSync(`${OUTPUT_PATH}${sep}cocos-js`);
  dirs.forEach((dir) => {
    const stat = fs.statSync(`${OUTPUT_PATH}${sep}cocos-js${sep}${dir}`);
    if (stat.isFile()) {
      FILE_MAPPING[`./${dir}`] = dir.replace(".js", "");
      FILE_MAPPING[`${dir}`] = dir.replace(".js", "");
    }
  });
}

function judgeIndexTemplate() {
  const { loadingPage } = PARAMS;
  if (loadingPage === "NULL") {
    INDEX_TEMPLATE = readFile(`${__dirname}${sep}..${sep}static${sep}html${sep}index_common.html`);
  } else {
    INDEX_TEMPLATE = readFile(`${__dirname}${sep}..${sep}static${sep}html${sep}index_${loadingPage}.html`);
  }
}

function resolveMapping(mapping) {
  const bundleString: string = mapping["chunks/bundle.js"];
  const bundleLine: string[] = bundleString.split("\n");
  const newBundleLines: string[] = [];
  bundleLine.forEach((line) => {
    libsNameArr.forEach((libName) => {
      line = line.startsWith(`System.register("chunks:///_virtual/${libName}`)
        ? ""
        : line;
    });
    line && newBundleLines.push(line);
  });
  mapping["chunks/bundle.js"] = newBundleLines.join("\n");
}

function importLibsScript() {
  const { libs } = PARAMS;
  if (libs[0]) {
    const libScript = readFile(`${__dirname}${sep}..${sep}library${sep}${libsNameArr[0]}.js`);
    INDEX_TEMPLATE = INDEX_TEMPLATE.replace("{#libsScript}", libScript);
  } else {
    INDEX_TEMPLATE = INDEX_TEMPLATE.replace("{#libsScript}", "");
  }
}

/**
 * 读取cocos-js文件夹下的所有代码代码
 * 剔除asm
 * 剔除wasm TODO
 *
 * @param scripts
 */
function compileEngine(scripts) {
  const dirs = fs.readdirSync(`${OUTPUT_PATH}${sep}cocos-js`);
  const asmModule = dirs.find((dir) => dir.startsWith("bullet.cocos"));
  const wasmModule = dirs.find((dir) => dir.startsWith("bullet.wasm"));
  const instantiated = dirs.find((dir) => dir.startsWith("instantiated"));
  const target = `return n=e?await t.import("./${wasmModule}"):await t.import("./${asmModule}")`;
  const cullingAsm = PARAMS.cullingAsm, cullingWasm = PARAMS.cullingWasm;
  if (cullingAsm != cullingWasm) {
    let script = readFile(`${OUTPUT_PATH}${sep}cocos-js${sep}${instantiated}`);
    if (cullingAsm) {
      script = script.replace(
        target,
        `return n=await t.import("./${wasmModule}")`
      );
      dirs.splice(dirs.indexOf(asmModule), 1);
    }
    if (cullingWasm) {
      script = script.replace(
        target,
        `return n=await t.import("./${asmModule}");`
      );
      dirs.splice(dirs.indexOf(wasmModule), 1);
    }
    // 写入文件
    fs.writeFileSync(`${OUTPUT_PATH}${sep}cocos-js${sep}${instantiated}`, script);
  }
  dirs.forEach((dir) => {
    const stat = fs.statSync(`${OUTPUT_PATH}${sep}cocos-js${sep}${dir}`);
    if (stat.isFile()) {
      if (!dir.startsWith("bullet.wasm")) {
        const script = readFile(`${OUTPUT_PATH}${sep}cocos-js${sep}${dir}`).replace(`System.register(`, `System.register('${dir}',`);
        scripts.push(complieFile(null, resolveScript(script)));
      } else {
        const asset = fs.readdirSync(`${OUTPUT_PATH}${sep}cocos-js${sep}assets`)[0];
        const buffer = fs.readFileSync(`${OUTPUT_PATH}${sep}cocos-js${sep}assets${sep}${asset}`);
        const script = `System.register('${dir}', [],(function(e,t){"use strict";return{execute:function(){var binary_string=window.atob("${buffer.toString("base64")}");
        var len=binary_string.length;var bytes=new Uint8Array(len);for(var i=0;i<len;i++){bytes[i]=binary_string.charCodeAt(i)}var blob=new Blob([bytes],{type:"${mime.lookup(`${OUTPUT_PATH}${sep}cocos-js${sep}assets${sep}${asset}`)}"});
        e("default",URL.createObjectURL(blob))}}}));`;
        scripts.push(complieFile(null, resolveScript(script)));
      }
    }
  });
}

function resolveBundle(url, res) {
  return (
    "<script>\n" +
    res.replace("System.register([", `System.register("${url}",[`) +
    "\n</script>"
  );
}

/**
 * 读取assets入口文件
 * 按文件前缀剔除不相关的ts脚本
 *
 * @param scripts
 */
function complieAssetsIndex(scripts, country_code) {
  const dirs = fs.readdirSync(`${OUTPUT_PATH}${sep}assets`);
  const SCRIPT_PREFIX = PARAMS.scriptPrefix ? PARAMS.scriptPrefix.split(',') : [];
  dirs.forEach((dir) => {
    let script = "";
    // 读取文件夹下的入口文件
    const lines = readFile(`${OUTPUT_PATH}${sep}assets${sep}${dir}${sep}index.js`).split("\n");
    lines.forEach((line) => {
      if (line?.startsWith('System.register("chunks:///_virtual/main",') && SCRIPT_PREFIX.length > 0) {
        const start = 'System.register("chunks:///_virtual/main",['.length;
        const end = line.indexOf("],(function(){");
        const scripts = line.substring(start, end);
        const imported = scripts.split(",");
        const matched = imported.filter(v => {
          return SCRIPT_PREFIX.some(prefix => v.startsWith(`"./${prefix}`));
        });
        script += line.replace(scripts, matched.join(",").toString());
      } else if (line?.startsWith('System.register("chunks:///_virtual/') && SCRIPT_PREFIX.length > 0) {
        if (SCRIPT_PREFIX.some(prefix => line.startsWith(`System.register("chunks:///_virtual/${prefix}`)) || line.startsWith(`System.register("chunks:///_virtual/Common`)) {
          if (country_code) {
            line = line.replace("this.curCity", `"${country_code}"`);
          }
          line = line.replace("this.curPlatform", `"${PARAMS.adPlatform}"`);
          script += line;
        }
      } else {
        if (country_code) {
          line = line.replace("this.curCity", `"${country_code}"`);
        }
        line = line.replace("this.curPlatform", `"${PARAMS.adPlatform}"`);
        script += line;
      }
    });
    scripts.push(script);
  });
}

/**
 * 读取assets资源
 *
 * @param scripts
 */
function complieAssetsResource(mapping, country_code) {
  const dirs = fs.readdirSync(`${OUTPUT_PATH}${sep}assets`);
  dirs.forEach(dir => {
    compileResource(`${OUTPUT_PATH}${sep}assets${sep}${dir}`, mapping, country_code);
  });
}

/**
 * 处理项目文件
 *
 * @param scripts
 * @param mapping
 */
function compileProject(scripts, mapping) {
  const version = PARAMS.editorVersion;
  const index = readFile(`${OUTPUT_PATH}${sep}index.js`).replace(`System.register(`, `System.register('index.js',`);
  const myApplication = readFile(`${__dirname}${sep}template${sep}application.js`);
  let application = readFile(`${OUTPUT_PATH}${sep}application.js`).replace(
    `System.register(`,
    `System.register('application.js',`
  );
  if (version != "3.5") {
    application = readFile(
      `${__dirname}${sep}..${sep}static${sep}${version}${sep}application.js`
    ).replace("return myApplication;", myApplication);
  } else {
    application = resolveApplication(application);
  }

  const logger = readFile(`${__dirname}${sep}template${sep}tk_pa_logger.js`);
  const dapi = PARAMS.adPlatform == "ironsource" ? complieFile(`${__dirname}${sep}template${sep}dapi.js`) : "";
  const install = readFile(`${__dirname}${sep}template${sep}install.js`);
  let setup = readFile(`${__dirname}${sep}template${sep}setup.js`);


  let code =
    `window.PROJECT=${JSON.stringify({
      playable_id: PARAMS.playableId,
      playable_name: PARAMS.playableName,
      ad_platform: PARAMS.adPlatform,
      android_url: PARAMS.androidUrl,
      ios_url: PARAMS.iosUrl,
    })};`

  if (PARAMS.comPressInstall) {
    if (PARAMS.adPlatform === "applovin" || PARAMS.adPlatform === "mintegral") {
      PARAMS.comPressInstall = true
    } else {
      //unity跟moloco默认不能压缩链接数据 其他的发的少平台的都默认false
      PARAMS.comPressInstall = false
    }
  }


  PARAMS.comPressInstall ? scripts.push(complieFile(null, code)) : scripts.push(code);

  if (!PARAMS.logger) {
    setup = setup.replace("window.TK && window.TK.init(window.PROJECT);", "");
  }

  SETUP_STR = setup;
  scripts.push(logger);
  scripts.push(dapi);

  PARAMS.comPressInstall ? scripts.push(complieFile(null, install)) : scripts.push(install);
  // scripts.push(install)
  scripts.push(resolveScript(index));
  scripts.push(resolveScript(application));

  mapping["settings.json"] = readFile(`${OUTPUT_PATH}${sep}src${sep}settings.json`);
  mapping["chunks/bundle.js"] = readFile(`${OUTPUT_PATH}${sep}src${sep}chunks${sep}bundle.js`);
}

function resolveApplication(application) {
  return application
    .replace(
      `return loadSettingsJson(cc);`,
      readFile(`${__dirname}${sep}template${sep}application.js`)
    )
    .replace(
      `return topLevelImport(pack);`,
      `var name = pack.replace("./src/", "");var blob = new Blob([window.resMap[name]], { type: "text/plain" });return topLevelImport(URL.createObjectURL(blob));`
    )
    .replace(
      `console.log("Success to load scene: ".concat(launchScene));`,
      `window.TK && window.TK.start();console.log("Success to load scene: ".concat(launchScene));`
    );
}

function resolveScript(content) {
  Object.keys(FILE_MAPPING).forEach((key) => {
    content = content.replace(key, FILE_MAPPING[key]);
  });
  return content;
}

function readFile(path) {
  return fs.readFileSync(path, { encoding: "utf-8" });
}

/**
 * 文件压缩
 *
 * @param path
 * @param content
 * @returns
 */
function complieFile(path, content = null): string | null {
  let file = "";
  if (path && "string" === typeof path) {
    file = readFile(path);
  } else if (Array.isArray(path)) {
    path.forEach((v) => {
      file += readFile(v);
    });
  } else if (content) {
    file = content;
  } else {
    console.log("path or content is required!!!");
    return null;
  }
  const isDeflate = PARAMS.isDeflate;
  const level = isDeflate ? 6 : 0;
  const compress = pako.deflate(file, { to: "string", level: level });
  const base64 = Buffer.from(compress).toString("base64");
  const res = `var compress = window.atob("${base64}", "base64");
    var bytes = new Uint8Array(compress.length);
    for (let i = 0; i < compress.length; i++) {
        bytes[i] = compress.charCodeAt(i);
    }
    var file = pako.inflate(bytes, { to: 'string' });
    eval(pako.inflate(bytes, { to: 'string' }));`;
  return res;
}

/**
 * 资源压缩
 *
 * @param path
 * @param mapping
 */
function compileResource(path, mapping, country_code) {
  const files = fs.readdirSync(path);
  files.forEach(fileName => {
    const absolutePath = `${path}${sep}${fileName}`;
    const stat = fs.statSync(absolutePath);
    if (stat.isFile() && !fileName.includes("index.js") && !fileName.includes("config.json")) {
      const relativePath = absolutePath.replace(`${OUTPUT_PATH}${sep}assets${sep}`, "");
      const mapping_key = sep == "/" ? relativePath : relativePath.replace(new RegExp(`${sep}${sep}`, "g"), "/");
      const mineType = mime.lookup(relativePath);
      const data = fs.readFileSync(absolutePath);
      if (data) {
        if (!country_code) {
          mapping[mapping_key] = `data:${mime.lookup(relativePath)};base64,${Buffer.from(data).toString("base64")}`;
        } else {
          if (!mineType || !mineType.includes("image")) {
            mapping[mapping_key] = `data:${mime.lookup(relativePath)};base64,${Buffer.from(data).toString("base64")}`;
          } else {
            if (L10N_JSON[parse(fileName).name]) {
              const parts = L10N_JSON[parse(fileName).name].split("@");
              const l10n_path = parts[0].replace(`${sep}${parts[1]}${sep}`, `${sep}${country_code}${sep}`);
              let l10n_data;
              if (fs.existsSync(`${__dirname}${sep}..${sep}..${sep}..${sep}${l10n_path}`)) {
                l10n_data = fs.readFileSync(`${__dirname}${sep}..${sep}..${sep}..${sep}${l10n_path}`);
              } else {
                l10n_data = data;
              }
              mapping[mapping_key] = `data:${mime.lookup(relativePath)};base64,${Buffer.from(l10n_data).toString("base64")}`;
            } else {
              mapping[mapping_key] = `data:${mime.lookup(relativePath)};base64,${Buffer.from(data).toString("base64")}`;
            }
          }
        }
      }
    } else if (stat.isFile()) {
      const relativePath = absolutePath.replace(`${OUTPUT_PATH}${sep}assets${sep}`, "");
      const mapping_key = sep == "/" ? relativePath : relativePath.replace(new RegExp(`${sep}${sep}`, "g"), "/");
      if (relativePath !== `main${sep}index.js`) {
        mapping[mapping_key] = readFile(absolutePath);
      }
    }
    if (stat.isDirectory()) {
      compileResource(absolutePath, mapping, country_code);
    }
  });
}
